#include <cstdlib>


using namespace std;

typedef short int CellType;  //Cell type is also net type
typedef short int PositionType;
//typedef pair<CellType, CellType> Connection;
typedef int CostType;

class TerminalNode {
public:
	// CellNum, TerminalNum, NetNum
	// CellNum of -1 represents feedthrough cell
	CellType cellNum;
	CellType termNum;
	CellType netNum;
	TerminalNode(CellType cell, CellType term, CellType net) {
		cellNum = cell;
		termNum = term;
		netNum = net;
	}
	void setCellNode(CellType cell, CellType term, CellType net) {
		cellNum = cell;
		termNum = term;
		netNum = net;
	}
	TerminalNode() {
		cellNum = -2;
		termNum = -2;
		netNum = -2;
	}
};

class Cell {
public:
	PositionType position[2]; // position[0]=x position[1]=y
	bool mirror;  // 1 for mirrored
	bool flip; // 1 for upside down
	vector<TerminalNode> terminal[4];  //list of cells connected each terminal
	CostType cost;
	
	Cell() {
		cost = 0;
		position[0]=-1;
		position[1]=-1;
		mirror=false;
		flip=false;
	}
	
	void toggleMirror() {
		mirror = !mirror;
	}
	
	void toggleFlip() {
		flip = !flip;
	}

	bool isBottom(CellType terminalNumber, bool testFlip) {
		if(!testFlip) {
			return((!flip && terminalNumber > 1) || (flip && terminalNumber < 2));
		}
		else {
			return(!((!flip && terminalNumber > 1) || (flip && terminalNumber < 2)));
		}
	}
	
	void addConnection(CellType terminalConnect, CellType cellNum, CellType terminalNum, CellType netNum) {
		TerminalNode newNode(cellNum, terminalNum, netNum);
		terminal[terminalConnect].push_back (newNode);
	}
	
	void setPosition(PositionType X, PositionType Y) {
		position[0] = X;
		position[1] = Y;	
	}
	
	void prettyPrint() {
		cerr << "Cell Position: " << position[0] << " " << position[1] << endl;
		cerr << "Mirror: " << mirror << " Flip: " << flip << endl;
		cerr << "Cost: " << cost << endl;
		for(int i = 0; i < 4; i++) {
			cerr << "Terminal " << i+1 << ": ";
			for(unsigned int j = 0; j < terminal[i].size(); j++) {
				cerr << "(" << terminal[i][j].cellNum << "," << terminal[i][j].termNum << ") ";
			}
			cerr << endl;
		}
	}
};
